package com.arrogames.blondbattle.game {
	import ash.core.Engine;
	import ash.core.Entity;
	import ash.core.System;
	import ash.integration.starling.StarlingFrameTickProvider;
	import com.arrogames.blondbattle.game.combat.Faction;
	import com.arrogames.blondbattle.game.movement.Position;
	import com.arrogames.blondbattle.game.rendering.CameraControlSystem;
	import com.arrogames.blondbattle.game.rendering.CameraRenderSystem;
	import com.arrogames.blondbattle.game.rendering.UIDisplay;
	import com.arrogames.blondbattle.game.state.Money;
	import com.arrogames.blondbattle.game.movement.Spawner;
	import com.arrogames.blondbattle.game.ai.AISystem;
	import com.arrogames.blondbattle.game.rendering.AnimationSystem;
	import com.arrogames.blondbattle.game.combat.CombatSystem;
	import com.arrogames.blondbattle.game.purchases.CooldownSystem;
	import com.arrogames.blondbattle.game.combat.DeathSystem;
	import com.arrogames.blondbattle.game.combat.MissileSystem;
	import com.arrogames.blondbattle.game.purchases.OrderSystem;
	import com.arrogames.blondbattle.game.purchases.RewardingSystem;
	import com.arrogames.blondbattle.game.movement.SpawnSystem;
	import com.arrogames.blondbattle.game.combat.TargetingSystem;
	import com.arrogames.blondbattle.game.rendering.UIRenderSystem;
	import com.arrogames.blondbattle.game.state.VictorySystem;
	import com.arrogames.blondbattle.input.KeyPoll;
	import com.arrogames.blondbattle.input.TouchPoll;
	import com.arrogames.blondbattle.model.UnitDefinition;
	import com.arrogames.blondbattle.model.WorldDefinition;
	import com.arrogames.blondbattle.ui.GameScreen;
	import com.arrogames.blondbattle.xml.UnitParser;
	import feathers.data.ListCollection;
	import starling.display.Quad;
	import starling.utils.Color;
	
	import com.arrogames.blondbattle.game.movement.MovementSystem;
	import com.arrogames.blondbattle.game.rendering.RenderSystem;
	import com.arrogames.blondbattle.game.SystemPriorities;
	
	import com.arrogames.blondbattle.game.rendering.Display;
	
	import flash.geom.Rectangle;
	
	import starling.core.Starling;
	import starling.display.DisplayObjectContainer;
	
	public class GameEngine extends Engine {
		
		private var tickProvider:StarlingFrameTickProvider;
		private var config:GameConfig;
		private var _creator:EntityCreator;
		private var uicreator:UIEntityCreator;
		
		private var humanCommander:Entity;
		private var computerCommander:Entity;
		
		private var world:WorldDefinition;
		private var availableUnits:ListCollection;
		private var victorySystem:VictorySystem;
		
		private var _muted:Boolean;
		private var keypoll:KeyPoll;
		private var touchpoll:TouchPoll;
		
		public function GameEngine(displayContainer:GameScreen, pAvailableUnits:ListCollection) {
			super();
			this.availableUnits = pAvailableUnits;
			prepare();
			setupSystems(displayContainer);
		}
		
		private function prepare():void {
			tickProvider = new StarlingFrameTickProvider( Starling.current.juggler );
			tickProvider.add( update );
			
			config = new GameConfig();
			config.worldViewPort = new Rectangle(0, 0, Starling.current.stage.stageWidth, Starling.current.stage.stageHeight);
			config.uiViewPort = new Rectangle(0,0,Starling.current.stage.stageWidth, Starling.current.stage.stageHeight);
			
			_creator = new EntityCreator( this );
			uicreator = new UIEntityCreator( this );
			
			keypoll = new KeyPoll(Starling.current.nativeStage);
			touchpoll = new TouchPoll(Starling.current.stage);
		}
		
		public function setWorld(world:WorldDefinition):void {
			this.world = world;
			config.worldViewPort.width = world.size.width;
			config.worldViewPort.height = world.size.height;
		}
		
		public function start() : void {
			victorySystem.reset();
			setupEntities();
			setupUIEntities();
			tickProvider.start();
		}
		
		public function stop():void {
			tickProvider.stop();
			removeAllEntities();
		}
		
		public function started():Boolean {
			return tickProvider.playing;
		}
		
		private function setupSystems(displayContainer:GameScreen):void {
			victorySystem = new VictorySystem( uicreator );
			victorySystem.gameOver.add(onGameOver);
			
			addSystem( victorySystem, SystemPriorities.preUpdate );
			addSystem( new MovementSystem( config ), SystemPriorities.move );
			addSystem( new SpawnSystem(), SystemPriorities.preUpdate );
			addSystem( new OrderSystem(creator), SystemPriorities.preUpdate );
			addSystem( new CooldownSystem(creator), SystemPriorities.preUpdate );
			addSystem( new TargetingSystem(), SystemPriorities.update );
			addSystem( new CombatSystem(creator), SystemPriorities.update );
			addSystem( new RewardingSystem(), SystemPriorities.update );
			addSystem( new CameraControlSystem(keypoll, touchpoll, config.worldViewPort), SystemPriorities.update );
			addSystem( new MissileSystem(creator), SystemPriorities.resolveCollisions);
			addSystem( new DeathSystem(creator), SystemPriorities.resolveCollisions);
			addSystem( new AISystem (creator, availableUnits), SystemPriorities.stateMachines);
			addSystem( new RenderSystem( displayContainer.entityContainer, creator ), SystemPriorities.render );
			addSystem( new CameraRenderSystem( displayContainer.entityContainer, config.worldViewPort ), SystemPriorities.render );
			addSystem( new UIRenderSystem( displayContainer.uiContainer ), SystemPriorities.render );
			addSystem( new AnimationSystem(), SystemPriorities.render);
		}
		
		private function onGameOver():void {
			//eat this
		}
		
		private function setupEntities():void {
			creator.createCamera(config.uiViewPort);
			creator.createGame();
			creator.createBackground(config.worldViewPort.width);
			
			var humanFaction:Faction = new Faction(Faction.HUMAN);
			var cpuFaction:Faction = new Faction(Faction.COMPUTER);
			
			humanCommander = creator.createCommander(world.humanFaction.money, humanFaction);
			computerCommander = creator.createCommander(world.cpuFaction.money, cpuFaction);
			
			var groundHeight:Number = 50;
			creator.createGround(config.worldViewPort.width, groundHeight, config.worldViewPort.x, config.worldViewPort.height - groundHeight);
			
			var baseY:Number = config.worldViewPort.height / 3;
			creator.createBase(world.humanFaction.baseX, config.worldViewPort.height - groundHeight, humanFaction, world.humanFaction.baseHP);
			creator.createSpawner(world.humanFaction.spawnX, config.worldViewPort.height - groundHeight, humanFaction);
			
			creator.createBase(world.cpuFaction.baseX, config.worldViewPort.height - groundHeight, cpuFaction, world.cpuFaction.baseHP);
			creator.createSpawner(world.cpuFaction.spawnX, config.worldViewPort.height - groundHeight, cpuFaction);
			
			var units:Array = UnitParser.parse();
		}
		
		private function setupUIEntities():void {
			
			uicreator.createMuteButton(_muted);
			uicreator.createMoneyLabel( config.uiViewPort.width / 2, 10, humanCommander.get(Money) as Money);
			uicreator.createMoneyLabel( config.uiViewPort.width / 2, 30, computerCommander.get(Money) as Money);
			
			var units:Array = UnitParser.parse();
			var buttonSize:Number = 80;
			var gap:Number = 2;
			var x:Number = config.uiViewPort.width - buttonSize * 3 - gap * 2 - 10;
			var y:Number = 10;
			var unit:UnitDefinition;
			for (var i:int = 0; i < units.length; i++) {
				unit = units[i] as UnitDefinition;
				
				uicreator.createPurchaseButton(unit, x, y, buttonSize);
				x += buttonSize+gap;
				if (y % 3 == 0) {
					y += buttonSize+gap;
				}
			}
		}
		
		public function playerOrderedUnit(unit:UnitDefinition):void {
			creator.createUnitOrder(unit, humanCommander.get(Faction) as Faction);
			creator.createUnitOrder(unit, computerCommander.get(Faction) as Faction);
		}
		
		public function mute():void {
			_muted = true;
		}
		
		public function unmute():void {
			_muted = false;
		}
		
		public function get creator():EntityCreator {
			return _creator;
		}
	}
}